package org.javahispano.javacup.modelo.util;

import org.javahispano.javacup.modelo.TacticaDetalle;
import org.javahispano.javacup.render.EstiloUniforme;
import java.awt.Color;
import java.util.HashSet;

/**Clase usada para validar una tactica*/
public final class ValidaTactica {

    /**Clase para Validar implementaciones tactica*/
    public static void validarDetalle(String nombre, TacticaDetalle t) throws Exception {
        if (t == null) {
            throw new Exception(nombre + "TacticaDetalle null");
        }
        if (t.getColorCalcetas() == null ||
                t.getColorCamiseta() == null ||
                t.getColorFranja() == null ||
                t.getColorPantalon() == null ||
                t.getColorPortero() == null) {
            throw new Exception(nombre + "TacticaDetalle: ColorCalcetas , ColorCamiseta , ColorFranja , ColorPantalon o ColorPortero es nulo");
        }
        if (t.getEstilo() == null) {
            throw new Exception(nombre + "TacticaDetalle: estilo es nulo");
        }
        if (t.getEntrenador() == null || t.getNombre() == null || t.getPais() == null) {
            throw new Exception(nombre + "TacticaDetalle: Entrenador, Nombre o Pais nulo");
        }
        if (t.getEntrenador().trim().length() == 0 ||
                t.getNombre().trim().length() == 0 ||
                t.getPais().trim().length() == 0) {
            throw new Exception(nombre + "TacticaDetalle: Entrenador, Nombre o Pais vacio");
        }
        if (t.getJugadores() == null) {
            throw new Exception(nombre + "TacticaDetalle: Jugadores nulo");
        }

        if (t.getJugadores().length != 11) {
            throw new Exception(nombre + "TacticaDetalle: Cantidad de Jugadores distinto de 11");
        }

        int porteros = 0;
        double creditos = 0;
        HashSet<Integer> set = new HashSet<Integer>();
        for (int i = 0; i < 11; i++) {
            if (t.getJugadores()[i] == null) {
                throw new Exception(nombre + "TacticaDetalle: Jugador[" + i + "] nulo");
            }
            if (t.getJugadores()[i].getColorPelo() == null || t.getJugadores()[i].getColorPiel() == null) {
                throw new Exception(nombre + "TacticaDetalle: Jugador[" + i + "] ColorPiel o ColorPelo nulo");
            }
            if (t.getJugadores()[i].getNombre() == null) {
                throw new Exception(nombre + "TacticaDetalle: Jugador[" + i + "] Nombre nulo");
            }
            if (t.getJugadores()[i].getNumero() <= 0 || t.getJugadores()[i].getNumero() > 99) {
                throw new Exception(nombre + "TacticaDetalle: Jugador[" + i + "] Numero fuera del rango [1,99]");
            }
            if (set.contains(t.getJugadores()[i].getNumero())) {
                throw new Exception(nombre + "TacticaDetalle: Numero de jugador " + t.getJugadores()[i].getNumero() + " repetido");
            }
            set.add(t.getJugadores()[i].getNumero());
            if (t.getJugadores()[i].getPresicion() < 0 || t.getJugadores()[i].getPresicion() > 1) {
                throw new Exception(nombre + "TacticaDetalle: Jugador[" + i + "] con presicion fuera del rango [0,1]");
            }
            if (t.getJugadores()[i].getRemate() < 0 || t.getJugadores()[i].getRemate() > 1) {
                throw new Exception(nombre + "TacticaDetalle: Jugador[" + i + "] con remate fuera del rango [0,1]");
            }
            if (t.getJugadores()[i].getVelocidad() < 0 || t.getJugadores()[i].getVelocidad() > 1) {
                throw new Exception(nombre + "TacticaDetalle: Jugador[" + i + "] con velocidad fuera del rango [0,1]");
            }
            creditos = creditos + t.getJugadores()[i].getPresicion();
            creditos = creditos + t.getJugadores()[i].getVelocidad();
            creditos = creditos + t.getJugadores()[i].getRemate();
            if (t.getJugadores()[i].esPortero()) {
                porteros++;
            }
        }
        creditos = (int) (creditos * 10000) / 10000d;
        if (porteros != 1) {
            throw new Exception(nombre + "TacticaDetalle: Cantidad porteros distinto de 1");
        }
        if (creditos > Constantes.CREDITOS_INICIALES) {
            throw new Exception(nombre + "TacticaDetalle: Uso " + creditos + " creditos, pero son permitidos " + Constantes.CREDITOS_INICIALES);
        }
        if (uniformesMuyParecidos(t)) {
            //throw new Exception(nombre + "TacticaDetalle: modificar colores de la camiseta, muy parecidos al uniforme alternativo ");
        }
    }

    /**Valida una alineacion para el saque y para la recepcion*/
    public static Posicion[][] validarPosicion(String nombre, Posicion[] saca, Posicion[] recibe) throws Exception {
        Posicion[] recibe0=new Posicion[11],saca0=new Posicion[11];
        for(int i=0;i<11;i++){
            if (recibe[i] == null) {
                throw new Exception("Alineacion Recibe[" + i + "] nulo");
            }
            if (saca[i] == null) {
                throw new Exception("Alineacion Saca[" + i + "] nulo");
            }
            recibe0[i]=new Posicion(recibe[i]);
            saca0[i]=new Posicion(saca[i]);
        }
        if (recibe == null) {
            throw new Exception("Alineacion Recibe nulo");
        }
        if (saca == null) {
            throw new Exception("Alineacion Recibe nulo");
        }
        if (recibe.length != 11) {
            throw new Exception("Alineacion Recibe tamaño distinto de 11");
        }
        if (saca.length != 11) {
            throw new Exception("Alineacion Saca tamaño distinto de 11");
        }
        for (int i = 0; i < 11; i++) {
            if (saca0[i].getY() > 0) {
                saca0[i] = new Posicion(saca0[i].getX(), 0);
            }
            if (recibe0[i].getY() > 0) {
                recibe0[i] = new Posicion(recibe0[i].getX(), 0);
            }
            if (recibe0[i].distancia(Constantes.centroCampoJuego) <= Constantes.RADIO_CIRCULO_CENTRAL) {
                double ang = Constantes.centroCampoJuego.angulo(recibe0[i]);
                recibe0[i] = Constantes.centroCampoJuego;
                recibe0[i] = recibe0[i].moverAngulo(ang, Constantes.RADIO_CIRCULO_CENTRAL + 1);
            }
        }
        return new Posicion[][]{saca0, recibe0};
    }

    private static double distancia(Color c1, Color c2) {
        return Math.sqrt((c1.getRed() - c2.getRed())*(c1.getRed() - c2.getRed()) + (c1.getGreen() - c2.getGreen())*(c1.getGreen() - c2.getGreen()) + (c1.getBlue() - c2.getBlue())*(c1.getBlue() - c2.getBlue()));
    }

    private static Color mesclarColor(Color c1, Color c2, double p1) {
        double p2 = 1d - p1;
        return new Color((int) (c1.getRed() * p1 + c2.getRed() * p2), (int) (c1.getGreen() * p1 + c2.getGreen() * p2), (int) (c1.getBlue() * p1 + c2.getBlue() * p2));
    }

    private static double getP1(EstiloUniforme est) {
        switch (est) {
            case LINEAS_HORIZONTALES:
                return .5;
            case LINEAS_VERTICALES:
                return .5;
            case FRANJA_VERTICAL:
                return .8;
            case FRANJA_HORIZONTAL:
                return .8;
            case FRANJA_DIAGONAL:
                return .8;
            case SIN_ESTILO:
                return 1;
        }
        return 0;
    }
    private static double umbral = 150;

    /**Indica true si es necesario que el equipo visita cambie a su uniforme alternativo*/
    public static boolean usarUniformeAlternativo(TacticaDetalle local, TacticaDetalle visita) {
        Color cl1, cv1, cv2;
        cl1 = mesclarColor(local.getColorCamiseta(), local.getColorFranja(), getP1(local.getEstilo()));
        cv1 = mesclarColor(visita.getColorCamiseta(), visita.getColorFranja(), getP1(visita.getEstilo()));
        cv2 = mesclarColor(visita.getColorCamiseta2(), visita.getColorFranja2(), getP1(visita.getEstilo2()));
        double d1=distancia(cl1, cv1);
        double d2=distancia(cl1, cv2);
        return d1 < umbral && d2 > d1;
    }

    /**Indica true si los dos unifermes de una tactica son muy parecidos*/
    public static boolean uniformesMuyParecidos(TacticaDetalle local) {
        Color cl1, cl2;
        cl1 = mesclarColor(local.getColorCamiseta(), local.getColorFranja(), getP1(local.getEstilo()));
        cl2 = mesclarColor(local.getColorCamiseta2(), local.getColorFranja2(), getP1(local.getEstilo2()));
        double d = distancia(cl1, cl2);
        return d < umbral;
    }
}
